import csv
import json
import os
import subprocess
from typing import List

import pandas as pd
import psutil
from fastapi import FastAPI, HTTPException, Query,Request
import uvicorn
from starlette.responses import HTMLResponse, FileResponse
import presscheck
import platformcmd
import presschmod,prehandle

from locust_selenium import Locust_web_auto

app = FastAPI()


@app.get("/")
async def index():
    return {"data": '欢迎!!!'}


# 测试
@app.get("/test")
async def test():
    return {"data": "success"}

@app.post("/start_web_auto")
async def start_web_auto(data: dict):
    Locust_web_auto.init()
    Locust_web_auto.start_load_test(data["users"],data["hatch_rate"])
    return {"data": '已执行'}

@app.post("/stop_web_auto")
async def stop_web_auto(data: dict):
    Locust_web_auto.init()
    Locust_web_auto.stop_load_test()
    return {"data": '已执行'}

# bot.log转换csv
@app.post("/log_to_csv")
async def log_to_csv(data: dict):
    filepath = data [ 'log_filepath' ]
    prehandle.log_to_csv_withoutTotal(filepath)
    return {"data": '已执行'}

# 覆盖协议及任务
@app.post("/log_protocols")
async def log_protocols(data: dict):
    message_dict = presscheck.log_protocols(procover_dict=data)
    return {"data": message_dict}


# 错误码统计
@app.post("/log_errcodes")
async def log_errcodes(data: dict):
    message_dict = presscheck.log_errcodes(logercode_dict=data)
    return {"data": message_dict}


# 权重统计
@app.post("/feature_weight")
async def feature_weight(data: dict):
    message_dict = presscheck.feature_weight(weight_dict=data)
    return {"data": message_dict}


# 执行命令
@app.post("/run_command")
async def run_command(data: dict):
    message_data = platformcmd.run_command(command=data [ 'cmd' ])
    return {"data": message_data}


# 统计结果
@app.post("/stats_problem")
async def stats_problem(data: dict):
    message_dict = presscheck.stats_problem(problem_dict=data)
    return {"data": message_dict}


# 替换---改配置
@app.post("/modify_file_content")
async def modify_file_content(data: dict):
    filepath = data [ 'filepath' ]
    old_content_regex = data [ 'old_content_regex' ]
    new_content = data [ 'new_content' ]
    presschmod.modify_file_content(file_path=filepath, regex=old_content_regex, new_content=new_content)
    return {"data": '已执行'}


@app.get("/catfile")
# async def downfile(file_path, download: bool = False):
async def downfile(file_path: str = Query(...),download: bool = Query(False)):
    if not os.path.exists(file_path):
        raise HTTPException(status_code=404, detail="File not found")
    # with open(file_path, 'r', encoding='utf-8') as f:
    #     reader = csv.reader(f)
    #     data = list(reader)

    with open(file_path, 'r', encoding='utf-8') as log_file:
        lines = log_file.readlines()

    # Step 1: 找到最后一个 INFO 行，并定位到表格起始位置
    last_info_index = None
    for i in range(len(lines)):
        if "INFO" in lines[i] and "UserResponse" in lines[i + 1]:
            last_info_index = i

    if last_info_index is None:
        print("未找到有效的 INFO 行")
        return

    # Step 2: 从最后一个 INFO 行向后找，找到第一个含 "Name" 的表格标题行
    header_line = None
    start_idx = None
    for i, line in enumerate(lines[last_info_index:], start=last_info_index):
        if "Name" in line and "|" in line:
            header_line = line.strip()
            start_idx = i
            break

    if not header_line:
        print("未能识别到表头行")
        return

    # Step 3: 提取表头
    headers = [col.strip() for col in header_line.split('|') if col.strip()]

    # Step 4: 提取数据行，直到遇到分隔线
    table_data = []
    for line in lines[start_idx + 2:]:  # 跳过表头和下一行的分隔线
        if "-" in line and len(line.strip()) > 0 and set(line.strip()) == {"-"}:
            break  # 遇到全为 '-' 的分割线，结束提取
        if "|" in line:
            row = [col.strip() for col in line.split('|') if col.strip()]
            if row:
                table_data.append(row)

    # Step 5: 写入 CSV，使用原文件名，替换后缀
    base_name = os.path.splitext(file_path)[0]  # 去掉原后缀
    filename = f"{base_name}.csv"


    with open(filename, 'w', newline='', encoding='utf-8') as csv_file:
        writer = csv.writer(csv_file)
        writer.writerow(headers)
        writer.writerows(table_data)

    with open(filename, 'r', encoding='utf-8') as csv_in:
        reader = csv.reader(csv_in)
        data = list(reader)
    if download:
        return FileResponse(
            path=file_path,
            media_type="text/csv",
            headers={
                "Content-Disposition": f'attachment; filename="{os.path.basename(file_path)}"'
            }
        )
    else:
        #创建HTML内容
        html_content = f"""
        <!DOCTYPE html>
        <html lang="en">
        <head>
            <meta charset="UTF-8">
            <title>Data</title>
            <style>
                table {{
                    width: 100%;
                    border-collapse: collapse;
                    margin: 25px 0;
                    font-family: Arial, sans-serif;
                }}

                th, td {{
                    padding: 12px;
                    text-align: left;
                    border-bottom: 1px solid #ddd;
                }}

                tr:hover {{
                    background-color: #f5f5f5;
                }}
            </style>
        </head>
        <body>
            <h1>Data</h1>
            <table>
                {''.join(f"<tr>{''.join(f'<td>{cell}</td>' for cell in row)}</tr>" for row in data)}
            </table>
        </body>
        </html>
                """

        return HTMLResponse(content=html_content, status_code=200)

@app.get("/catfiles")
async def downfiles(file_path: List[str] = Query(...), output_path: str = Query(...), download: bool = Query(False)):

    print(file_path)
    file_paths = [fp.strip() for fp in file_path]
    print(file_paths)

    if not file_paths:
        raise HTTPException(status_code=400, detail="No CSV files provided")

    dfs = []
    for i, csv_file in enumerate(file_paths):
        df = pd.read_csv(csv_file)
        if i == 0:
            dfs.append(df)
        else:
            dfs.append(df.iloc[1:])  # 位置索引，只保留第一个表头

    # 合并数据
    merged_df = pd.concat(dfs, ignore_index=True)

    output_dir = os.path.dirname(output_path)
    if output_dir and not os.path.exists(output_dir):
        os.makedirs(output_dir)

    merged_df.to_csv(output_path, index=False, encoding='utf-8-sig')

    if download:
        return FileResponse(
            path=output_path,
            filename=os.path.basename(output_path),
            media_type="text/csv"
        )
    else:
        with open(output_path, 'r', encoding='utf-8') as f:
            reader = csv.reader(f)
            data = list(reader)
        # 创建HTML内容
        html_content = f"""
        <!DOCTYPE html>
        <html lang="en">
        <head>
            <meta charset="UTF-8">
            <title>Data</title>
            <style>
                table {{
                    width: 100%;
                    border-collapse: collapse;
                    margin: 25px 0;
                    font-family: Arial, sans-serif;
                }}

                th, td {{
                    padding: 12px;
                    text-align: left;
                    border-bottom: 1px solid #ddd;
                }}

                tr:hover {{
                    background-color: #f5f5f5;
                }}
            </style>
        </head>
        <body>
            <h1>Data</h1>
            <table>
                {''.join(f"<tr>{''.join(f'<td>{cell}</td>' for cell in row)}</tr>" for row in data)}
            </table>
        </body>
        </html>
                """

        return HTMLResponse(content=html_content, status_code=200)
# @app.post("/stop_bat")
# async def stop_bat(request: Request):
#     try:
#         results = []
#         data = await request.json()
#         print("data:", type(data))
#         if isinstance(data, dict) and 'bat_path' in data:
#             value = data['bat_path']
#             if isinstance(value, str):  # 如果是字符串，转成单元素列表
#                 bat_files = [value.strip()]
#             elif isinstance(value, list):  # 如果是列表，处理每个元素
#                 bat_files = [f.strip() for f in value if isinstance(f, str)]
#                 print("bat_files:", bat_files)
#             else:
#                 return {"status": "error", "message": "bat_path 必须是字符串或字符串数组"}
#
#
#             for bat_file in bat_files:
#                 bat_name = os.path.basename(bat_file)
#                 # 查找所有匹配的进程 ID
#                 cmd_find = f'C:\\Windows\\system32\\wbem\\wmic process where "name=\'cmd.exe\' and commandline like \'%{bat_file}%\'" get ProcessId'
#                 result = subprocess.run(
#                     cmd_find,
#                     shell=True,
#                     stdout=subprocess.PIPE,
#                     stderr=subprocess.PIPE,
#                     text=True,
#                     encoding='utf-8',
#                     errors='ignore'
#                 )
#                 print("result:", result)
#                 output = result.stdout.strip()
#                 print("output:", output)
#                 pids = [line.strip() for line in output.splitlines() if line.strip().isdigit()]
#                 print("pids:", pids)
#                 for pid in pids:
#                     subprocess.run(f'C:\\Windows\\system32\\taskkill /F /T /PID {pid}', shell=True)
#
#                 results.append({
#                     "file": bat_file,
#                     "status": "success",
#                     "killed_pids": pids
#                 })
#                 print("results:", results)
#
#             return {"results": results}
#
#     except Exception as e:
#         print("error:", str(e))
#

@app.post("/shutdown_bat")
async def shutdown_bat(request: Request):
    try:
        data = await request.json()
        if not isinstance(data, dict) or 'bat_path' not in data:
            raise HTTPException(status_code=400, detail="请求必须包含bat_path字段")

        raw_paths = data['bat_path']
        if isinstance(raw_paths, str):
            raw_paths = [raw_paths]
        elif not isinstance(raw_paths, list):
            raise HTTPException(status_code=400, detail="bat_path必须为字符串或数组")

        results = []
        for raw_path in raw_paths:
            # 规范化为绝对路径并转义反斜杠
            bat_file = os.path.abspath(raw_path.replace('/', '\\')).strip()
            escaped_path = bat_file.replace('\\', '\\\\').replace("'", "\\'")
            bat_name = os.path.basename(bat_file)

            # 构造 PowerShell 命令
            wmic_cmd = [
                "powershell.exe",
                "-Command",
                f"Get-CimInstance Win32_Process -Filter \"Name = 'cmd.exe'\" | "
                f"Where-Object {{ $_.CommandLine -like '*{bat_name}*' }} | "
                f"Select-Object ProcessId, CommandLine"
            ]


            # # 构造WMIC查询（匹配cmd.exe进程）
            # wmic_cmd = (
            #     f"powershell.exe -Command "Get-CimInstance Win32_Process -Filter \"Name = 'cmd.exe'\"""
            #     f"Where-Object {{ $_.CommandLine -like '*{bat_file}*' }} | "
            #     f"Select-Object ProcessId, CommandLine"
            # )
            # 执行WMIC命令
            find_result = subprocess.run(
                wmic_cmd,
                shell=True,
                stdout=subprocess.PIPE,
                stderr=subprocess.PIPE,
                text=True,
                encoding='gbk'
            )
            print("find_result: ", find_result)
            # 提取PID和命令行
            pids = []
            cmd_lines = []
            for line in find_result.stdout.splitlines():
                if line.strip() and not line.startswith('ProcessId'):
                    parts = line.strip().split()
                    print("parts: ", parts)
                    if len(parts) >= 2 and parts[0].isdigit():
                        pid, cmd = parts[0], ' '.join(parts[1:])
                        pids.append(pid)
                        print("pids: ", pids)
                        print("cmd: ", cmd)
                        cmd_lines.append(cmd)

            # 验证PID是否存在
            # valid_pids = [pid for pid in pids if psutil.pid_exists(int(pid))]
            # print("valid_pids: ", valid_pids)
            # 终止cmd.exe父进程
            killed_cmd_pids = []
            failed_cmd_pids = []
            for pid in pids:
                kill_result = subprocess.run(
                    f'taskkill /F /T /PID {pid}',
                    shell=True,
                    stdout=subprocess.PIPE,
                    stderr=subprocess.PIPE,
                    text=True
                )
                print("kill_result: ", kill_result)
                if kill_result.returncode == 0:
                    killed_cmd_pids.append(pid)
                else:
                    failed_cmd_pids.append(pid)

            # 终止所有adb.exe子进程
            # adb_kill_result = subprocess.run(
            #     'taskkill /F /IM adb.exe',
            #     shell=True,
            #     stdout=subprocess.PIPE,
            #     stderr=subprocess.PIPE,
            #     text=True
            # )
            # 记录结果
            results.append({
                "file": raw_path,
                # "killed_adb_processes": adb_kill_result.returncode == 0,
                "killed_cmd_pids": killed_cmd_pids,
                "failed_cmd_pids": failed_cmd_pids,
                # "adb_kill_log": adb_kill_result.stdout
            })
            print("results: ", results)

        return {"results": results}

    except Exception as e:
        raise HTTPException(status_code=500, detail=str(e))


# 启动命令
# cd D:\CTC_Server_Projs\MicroServices_Projs\autotool
# uvicorn web:app --host 0.0.0.0 --port 8000
# 导出依赖
# pip freeze >requirements.txt

if __name__ == "__main__":
    uvicorn.run(app=app, host="0.0.0.0", port=29777)
    #uvicorn.run(app=app, host="10.12.28.253", port=8000)
